package com.sitech.ismp.workflow.engine.impl;

import com.sitech.ismp.common.exception.BsmException;
import com.sitech.ismp.common.server.SpringContext;
import com.sitech.ismp.workflow.dao.TaskDAO;
import com.sitech.ismp.workflow.dao.TaskStatusInfoDAO;
import com.sitech.ismp.workflow.domain.*;
import com.sitech.ismp.workflow.engine.*;
import com.sitech.ismp.workflow.outSend.SendNoticeHandLingQueryService;
import com.sitech.ismp.workflow.outside.WorkflowNotifyService;
import com.sitech.ismp.workflow.rule.DBRuleTask;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

public class ActivityExtendImpl implements ActivityExtend {
    private Log logger = LogFactory.getLog(ActivityExtendImpl.class);
    private DBRuleTask dbRuleTask;
    private TaskManager taskMgr;
    private TaskQueryService taskQueryService;
    private WorkflowNotifyFactory workflowNotifyFactory;
    private ProcessManager processManager;
    private TaskStatusInfoDAO taskStatusInfoDAO;
    private TimeoutCalculate timeoutCalculate;
    private HaveDoneTaskManager haveDoneTaskManager;
    private WorkflowNotifyService workflowNotifyService;
    private ActivityQueryService activityQueryService;
    private SendNoticeHandLingQueryService sendNoticeHandLingQueryService;
    private SubflowService subflowService;
    private TaskDAO taskDAO;

    public ActivityExtendImpl() {
    }

    public void setSubflowService(SubflowService subflowService) {
        this.subflowService = subflowService;
    }

    public void postAction(Task task, ActivityInfo nextActivityInfo, int preActiveTaskId) {
        try {
            if (((task.getActivityType() == 2) && (
                    nextActivityInfo.getActivityType() != 3)) ||
                    (task.getActivityType() == 1) ||
                    (task.getActivityType() == 10)) {
                this.logger.debug("Attention:db rule exec here.");

                String table_name = "HAVEDONETASKS";

                table_name = table_name + nextActivityInfo.getProcessId();


                this.dbRuleTask.start(table_name, task.getTaskId(), "2");
            } else if (task.getActivityType() == 3) {
                this.logger.debug("Attention:db rule exec here1.");

                String table_name = "HAVEDONETASKS";

                table_name = table_name + nextActivityInfo.getProcessId();


                this.dbRuleTask.start(table_name, preActiveTaskId, "2");
            }
        } catch (Exception exception) {
            this.logger.error("db_rule call error.", exception);
        }
    }

    public void preAction(ActivityInfo activityInfo, int taskId) {
        if ((activityInfo.getActivityType() == 2) ||
                (activityInfo.getActivityType() == 10)) {
            String table_name = "HAVEDONETASKS";

            table_name = table_name + activityInfo.getProcessId();
            this.dbRuleTask.start(table_name, taskId, "3");
        }
    }

    public Task noticeTask(int taskId, String message, String noticeType, String user) {
        Task task = this.taskQueryService.queryTaskById(taskId);
        int noticeTimes = task.getNoticeTimes();
        noticeTimes++;
        task.setNoticeTimes(noticeTimes);
        this.taskMgr.updateTask(task);
        return task;
    }

    public Task claimTask(int taskId, String user) {
        this.logger.info("日期:" + new Date() + ",用户：" + user + "作工单（任务ID：" + taskId + "）认领操作。");
        Task task = this.taskQueryService.queryTaskById(taskId);
        if ((task != null) && (!"".equals(task.getStaffWg())) && (2 == task.getTaskStatus())) {
            task.setStaffId(user);
            task.setTaskStatus(1);
            this.taskMgr.updateTask(task);
        } else {
            if (task == null) {
                throw new BsmException("", "任务已被完成");
            }
            throw new BsmException("", "任务已被认领");
        }
        return task;
    }

    public Task releaseTask(int taskId, String user) {
        this.logger.info("日期:" + new Date() + ",用户：" + user + "作工单（任务ID：" + taskId + "）释放操作。");
        Task task = this.taskQueryService.queryTaskById(taskId);
        if ((task != null) && (!"".equals(task.getStaffWg())) && (1 == task.getTaskStatus())) {
            task.setStaffId("");
            task.setTaskStatus(2);
            this.taskMgr.updateTask(task);
        } else {
            if (task == null) {
                throw new BsmException("", "任务已被完成");
            }
            throw new BsmException("", "任务释放失败，原因：该任务非工作组任务");
        }
        return task;
    }

    public void terminateProcess(int serialNo, String user, String desc) {
        this.logger.info("日期:" + new Date() + "用户：" + user + "作工单终止（流水号：" + serialNo + "）操作。");
        try {
            ProcessInstance processInstance = this.processManager.getProcessInstanceDAO().queryProcessInstanceBySerialNo(
                    serialNo);
            this.processManager.terminateProcess(serialNo);
            this.processManager.haveDoneProcessInstance(serialNo, 2);
            this.processManager.deleteProcessInstance(serialNo);
            deleteTaskStatus(serialNo);
            processInstance.setStatus(2);
            this.workflowNotifyFactory.notifyProcessComplete(processInstance);
        } catch (Exception e) {
            this.logger.error("回退失败" + e);
            throw new BsmException("", "任务回退失败，请联系管理员");
        }
    }

    public void renewProcess(int serialNo, String user, String desc) {
        this.logger.info("日期:" + new Date() + "用户：" + user + "作恢复终止工单（流水号：" + serialNo + "）操作。");
        try {
            String processId = this.processManager.getProcessInstanceDAO().queryProcessIdFromHaveDone(serialNo);
            HashMap map = new HashMap();
            map.put("serialNo", Integer.valueOf(serialNo));
            map.put("userId", user);
            map.put("processId", processId);
            this.processManager.renewProcess(serialNo, map);
        } catch (Exception e) {
            this.logger.error("回退失败" + e);
            throw new BsmException("", "终止工单回退失败，请联系管理员");
        }
    }

    public void completeProcess(int serialNo, int taskId) {
        complete(taskId);

        deleteTaskStatus(serialNo);

        ProcessInstance processInstance = this.processManager.getProcessInstanceDAO()
                .queryProcessInstanceBySerialNo(serialNo);
        this.processManager.haveDoneProcessInstance(serialNo, 5);
        this.processManager.deleteProcessInstance(serialNo);
        processInstance.setStatus(5);
        this.workflowNotifyFactory.notifyProcessComplete(processInstance);

        this.timeoutCalculate.setProcessEnd(processInstance);
    }

    private void complete(int taskId) {
        Task toDoTask = this.taskQueryService.queryTaskById(taskId);


        this.taskMgr.haveDoneProcess(toDoTask, 1);
    }

    private void deleteTaskStatus(int iseriealno) {
        this.taskStatusInfoDAO.deleteTaskStatusBySeriealNo(iseriealno);
    }

    public Task save(int taskId, String title, String user) {
        Task task = this.taskQueryService.queryTaskById(taskId);
        if ((title != null) && (!"".equals(title))) {
            task.setTitle(title);
        }
        task.setTaskStatus(3);
        this.taskMgr.updateTask(task);
        return task;
    }

    public Task transferTask(int taskId, Participant participant, String user) {
        this.logger.info("日期:" + new Date() + ",用户：" + user + "作工单（任务ID：" + taskId + "）转派操作，转派对象为：" +
                participant.getParticipantValue() + "。");
        Task task = this.taskQueryService.queryTaskById(taskId);
        int participantType = participant.getParticipantType();
        if ((participantType == 1) ||
                (participantType == 2) ||
                (participantType == 3)) {
            task.setTaskStatus(2);
            task.setStaffWg(participant.getParticipantValue());
            task.setStaffId("");
        } else {
            task.setTaskStatus(1);
            task.setStaffId(participant.getParticipantValue());
            task.setStaffWg("");
        }
        this.taskMgr.updateTask(task);
        return task;
    }

    public Task suspendTask(int taskId, String user, String desc) {
        this.logger.info("日期:" + new Date() + ",用户：" + user + "作任务（任务ID：" + taskId + "）挂起操作。");
        Task task = this.taskQueryService.queryTaskById(taskId);
        if (task != null) {
            task.setTaskStatus(4);
            this.taskMgr.updateTask(task);
        } else {
            throw new BsmException("", "任务挂起失败,原因：任务已被完成");
        }
        return task;
    }

    public Task wakeupTask(int taskId, String user, String desc) {
        this.logger.info("日期:" + new Date() + ",用户：" + user + "作任务（任务ID：" + taskId + "）唤醒操作。");
        Task task = this.taskQueryService.queryTaskById(taskId);
        if (task != null) {
            task.setTaskStatus(1);
            this.taskMgr.updateTask(task);
        } else {
            throw new BsmException("", "任务挂起失败,原因：任务已被完成");
        }
        return task;
    }

    public Task returnBackTask(Task curTask, String user, String desc) {
        this.logger.info("日期:" + new Date() + ",用户：" + user + "作任务（任务ID：" + curTask.getTaskId() + "）回退操作。");
        if (curTask != null) {
            int entityId = curTask.getEntityId();
            String table = "HAVEDONETASKS" + curTask.getProcessId();
            HaveDoneTask haveDoneTask = this.haveDoneTaskManager.getPreTaskByTaskIdWithTable(entityId, table);
            int hisActid = haveDoneTask.getActivityType() == 6 ? haveDoneTask.getEntityId() : haveDoneTask.getTaskId();
            int activityType = haveDoneTask.getActivityType();
            int hisTaskId = haveDoneTask.getTaskId();
            if ((11 != haveDoneTask.getActivityType()) &&
                    (12 != haveDoneTask.getActivityType()) &&
                    (1 != haveDoneTask.getActivityType())) {
                while (2 != haveDoneTask.getActivityType()) {
                    int tempEntityId = haveDoneTask.getEntityId();
                    haveDoneTask = null;
                    haveDoneTask = this.haveDoneTaskManager.getPreTaskByTaskIdWithTable(tempEntityId, table);
                }
                Task task = buildTask(haveDoneTask.getActivityType(), haveDoneTask.getBizDeadline(), haveDoneTask.getCurrActId(), haveDoneTask.getCurrDealer(),
                        haveDoneTask.getDateAccepted(), null, new Date(),
                        null, haveDoneTask.getEntityId(), null, haveDoneTask.getFromInstanceId(), haveDoneTask.getGrantorId(),
                        haveDoneTask.getInstanceId(), 0, haveDoneTask.getPreActId(), haveDoneTask.getPreTaskId(), curTask.getProcessId(),
                        haveDoneTask.getSerialNo(), haveDoneTask.getStaffId(), haveDoneTask.getStaffWg(),
                        haveDoneTask.getTaskId(), 1, haveDoneTask.getTitle());
                task.setDateAllow(this.timeoutCalculate.getTaskRollbackTimeLimit(task));

                insertSheetReachToTbIsmMsgSet(task);
                this.taskMgr.addToDoTaskList(task);


                this.taskDAO.deleteToDoTaskById(curTask.getTaskId());
                if (activityType == 6) {
                    this.haveDoneTaskManager.delHaveDoneTaskWithTable(hisTaskId, table);
                }
                this.haveDoneTaskManager.delHaveDoneTaskWithTable(hisActid, table);

                this.timeoutCalculate.deleteTaskTimeout(curTask);
                return task;
            }
            throw new BsmException("", "当前驱节点为与分支、与汇聚和开始节点时，不允许回退");
        }
        throw new BsmException("", "工单回退失败,原因：任务已被完成");
    }

    public void insertSheetReachToTbIsmMsgSet(Task task) {
        ActivityInfo activityInfo = this.activityQueryService.getActivity(task.getCurrActId());
        TbIsmMgsBeanClass tbIsmMgsBeanClass = this.sendNoticeHandLingQueryService.queryTbIsmMgsBeanClass(
                activityInfo.getProcessId(), task.getCurrActId(), 1);
        if (tbIsmMgsBeanClass != null) {
            String beanClass = tbIsmMgsBeanClass.getBeanClass();
            try {
                if ((beanClass != null) && (!beanClass.equals(""))) {
                    Object object = SpringContext.getBean(beanClass);
                    if ((object instanceof WorkflowNotifyService)) {
                        this.workflowNotifyService = ((WorkflowNotifyService) object);
                        this.workflowNotifyService.notifyTaskCreate(task);
                    }
                } else {
                    this.workflowNotifyService.notifyTaskCreate(task);
                }
            } catch (Exception localException) {
            }
        } else {
            this.workflowNotifyService.notifyTaskCreate(task);
        }
    }

    public Task buildTask(int activityType, Date bizDeadline, int currActId, String currDealer, Date dateAccepted, Date dateAllow, Date dateCreated, String dealType, int entityId, String execDbRule, int fromInstanceId, String grantorId, int instanceId, int noticeTimes, int preActId, int preTaskId, int processId, int serialNo, String staffId, String staffWg, int taskId, int taskStatus, String title) {
        Task task = new Task();
        task.setActivityType(activityType);
        task.setBizDeadline(bizDeadline);
        task.setCurrActId(currActId);
        task.setCurrDealer(currDealer);
        task.setDateAccepted(dateAccepted);
        task.setDateAllow(dateAllow);
        task.setDateCreated(dateCreated);
        task.setDealType(dealType);
        task.setEntityId(entityId);
        task.setExecDbRule(execDbRule);
        task.setFromInstanceId(fromInstanceId);
        task.setGrantorId(grantorId);
        task.setInstanceId(instanceId);
        task.setNoticeTimes(noticeTimes);
        task.setPreActId(preActId);
        task.setPreTaskId(preTaskId);
        task.setProcessId(processId);
        task.setSerialNo(serialNo);
        task.setStaffId(staffId);
        task.setStaffWg(staffWg);
        task.setTaskId(taskId);
        task.setTaskStatus(taskStatus);
        task.setTitle(title);
        return task;
    }

    public boolean browseTask(int taskId, String user, String desc) {
        this.logger.info("日期:" + new Date() + ",用户：" + user + "作任务（任务ID：" + taskId + "）浏览操作。");

        boolean b = false;
        Task task = this.taskQueryService.queryTaskById(taskId);
        if (task != null) {
            task.setBrowseFlag(1);
            this.taskMgr.updateTask(task);
            b = true;
        } else {
            throw new BsmException("", "任务浏览失败,原因：任务已被完成");
        }
        return b;
    }

    public String deleteProcessInstance(int serialNo, String deleteChildren, String user, String desc) {
        ProcessInstance processInstance = this.processManager.queryProcessInstanceInfoBySerialNo(serialNo);
        List childSerialList = null;
        String processId = "";
        List activityList = null;
        if (processInstance != null) {
            processId = String.valueOf(processInstance.getProcessId());
            activityList = this.taskDAO.getActivyIdByProcessId(String.valueOf(processId));
            childSerialList = this.taskDAO.getChildSerialNo(String.valueOf(serialNo));
            if (activityList != null) {
                if (this.taskDAO.deleteProcessInstanceData(String.valueOf(serialNo), processId, activityList)) {
                    if ((deleteChildren.equals("true")) && (childSerialList != null) && (childSerialList.size() > 0)) {
                        String tempResult = "";
                        for (int i = 0; i < childSerialList.size(); i++) {
                            HashMap tempMap = (HashMap) childSerialList.get(i);
                            tempResult = tempResult + deleteProcessInstance(Integer.parseInt((String) tempMap.get("TO_SERIALNO")), deleteChildren, user, desc);
                        }
                        if (tempResult.indexOf("错误") > 0) {
                            return tempResult + "提示：删除工单" + serialNo + "成功，但在删除其子工单过程中出错！";
                        }
                        return tempResult + "提示:删除工单" + serialNo + "及其子工单成功！";
                    }
                    this.taskDAO.deleteRelationshipBySeriNo(String.valueOf(serialNo));
                    return "提示:删除工单" + serialNo + "成功！";
                }
                return "错误：删除工单" + serialNo + "失败！";
            }
            return "错误:查找工单" + serialNo + "节点错误！";
        }
        return "错误：没有找到工单" + serialNo + "！";
    }

    public Log getLogger() {
        return this.logger;
    }

    public void setLogger(Log logger) {
        this.logger = logger;
    }

    public void setDbRuleTask(DBRuleTask dbRuleTask) {
        this.dbRuleTask = dbRuleTask;
    }

    public void setTaskMgr(TaskManager taskMgr) {
        this.taskMgr = taskMgr;
    }

    public void setTaskQueryService(TaskQueryService taskQueryService) {
        this.taskQueryService = taskQueryService;
    }

    public void setWorkflowNotifyFactory(WorkflowNotifyFactory workflowNotifyFactory) {
        this.workflowNotifyFactory = workflowNotifyFactory;
    }

    public void setProcessManager(ProcessManager processManager) {
        this.processManager = processManager;
    }

    public void setTaskStatusInfoDAO(TaskStatusInfoDAO taskStatusInfoDAO) {
        this.taskStatusInfoDAO = taskStatusInfoDAO;
    }

    public void setTimeoutCalculate(TimeoutCalculate timeoutCalculate) {
        this.timeoutCalculate = timeoutCalculate;
    }

    public void setHaveDoneTaskManager(HaveDoneTaskManager haveDoneTaskManager) {
        this.haveDoneTaskManager = haveDoneTaskManager;
    }

    public void setWorkflowNotifyService(WorkflowNotifyService workflowNotifyService) {
        this.workflowNotifyService = workflowNotifyService;
    }

    public void setActivityQueryService(ActivityQueryService activityQueryService) {
        this.activityQueryService = activityQueryService;
    }

    public void setSendNoticeHandLingQueryService(SendNoticeHandLingQueryService sendNoticeHandLingQueryService) {
        this.sendNoticeHandLingQueryService = sendNoticeHandLingQueryService;
    }

    public void setTaskDAO(TaskDAO taskDAO) {
        this.taskDAO = taskDAO;
    }

    public void reOpenSheet(String processId, String serialNo, String activityId, String user, String desc) {
        this.logger.info("日期:" + new Date() + "用户：" + user + "作重开工单（流水号：" + serialNo + "）操作。");
        try {
            HashMap map = new HashMap();
            map.put("serialNo", serialNo);
            map.put("userId", user);
            map.put("processId", processId);
            map.put("activityId", activityId);
            this.processManager.reOpenSheet(Integer.parseInt(serialNo), map);
        } catch (Exception e) {
            this.logger.error("重开失败" + e);
            throw new BsmException("", "重开工单失败，请联系管理员");
        }
    }
}
